package main

import (
	"fmt"
)

/*
堆分最大堆、最小堆。 以最xiao堆为例。

最xiao堆是一个完全二叉树。 并且要求每个结点的值必须xiao于他的两个子节点。 所以他的根结点一定是最xiao值。

但是左右结点大小不一定。

用数组表示的二叉树，可以这样表达： i的子节点下标为 2*i + 1 和 2 * i + 2.   i的父节点下标为 (i-1)/2。
对于数组长度length，大于length/2的下标一定没有子节点.
 
排序思想是构建最xiao堆，之后根节点就是最xiao的一个了，把根结点拿出来，再把剩下的堆整理成最xiao堆，再把根拿出来。循环直到最后一个元素。
*/
func main() {
	var sortArr []int
	sortArr = []int{2, 3, 4, 1, 6, 8, 9, 7, 0}
	fmt.Println(sortArr)
	HeapSort(sortArr)
	fmt.Println(sortArr)
	for _, v := range sortArr {
		fmt.Println(v)
	}
}

func HeapSort(values []int) {
	buildHeap(values)
	for i := len(values); i > 1; i-- {
		values[0], values[i-1] = values[i-1], values[0]
		adjustHeap(values[:i-1], 0)
		//fmt.Println("the heap is ", values)
	}
}

func buildHeap(values []int) {
	for i := len(values); i >= 0; i-- { //////一定得从后往前调整，
		adjustHeap(values, i)
	}
}

func adjustHeap(values []int, pos int) { ///////// 调整pos位置的结点
	node := pos
	length := len(values)
	for node < length {
		var child int = 0
		if 2*node+2 < length {
			if values[2*node+1] < values[2*node+2] {
				child = 2*node + 1
			} else {
				child = 2*node + 2
			} ////////选出xiao子节点
		} else if 2*node+1 < length {
			child = 2*node + 1
		}
		if child > 0 && values[child] < values[node] {
			values[node], values[child] = values[child], values[node]
			node = child
		} else {
			break
		}
	}
}
